Skip to content

Fix wrong module end addresses on macOS (LLDB adapter) (#554)#1112

Open
xusheng6 wants to merge 1 commit into
devfrom
test_fix_554_module_end_address
Open

Fix wrong module end addresses on macOS (LLDB adapter) (#554)#1112
xusheng6 wants to merge 1 commit into
devfrom
test_fix_554_module_end_address

Conversation

@xusheng6

@xusheng6 xusheng6 commented Jul 6, 2026

Copy link
Copy Markdown
Member

Summary

Fixes #554 — the Debugger Modules panel showed an end address of -1 (and a ~2.3 GB size) for every module on macOS.

Root cause

LldbAdapter::GetModuleList() computed a module's size as max(section end) - base over all of the module's sections. On macOS this is fundamentally broken because dyld does not map system libraries as independent images — it groups the segments of different modules by type into the shared cache:

  • all __TEXT segments are laid out together, all __DATA together, etc.;
  • a single combined __LINKEDIT (~600 MB) is shared by every module in the cache.

So a module's own segments are scattered across gigabytes, and dozens of modules point at the same __LINKEDIT. Taking the max section end therefore spanned most of the shared cache, producing an absurd size that rendered as end = -1 in the UI.

Verified against /usr/bin/ls with the shared cache mapped — every module reported ~0x9xxxxxxx (~2.3 GB); one module even chained through to 0x22b1d0000.

Fix

Compute the extent from the header segment, keeping it to the range the module actually owns via two signals:

  1. Clip at the next module's load base — a module owns [base, nextModuleBase), so segments that map into a foreign shared-cache region above the next module are dropped.
  2. Stop at the first large inter-segment gap (64 MB) — bounds the single highest-based module, which has no next base to clip against. Observed intra-module scatter on macOS is ≥ ~240 MB, so 64 MB cleanly separates a module's own contiguous segments from the shared-cache jump while staying well above any inter-segment gap on Linux.

On Linux and for the main executable on macOS (contiguous segments), this yields the true full extent; for shared-cache dylibs it yields the contiguous __TEXT range, which is what image list/vmmap report as the module's range.

Verification

Simulated the exact algorithm against /usr/bin/ls (48 modules, shared cache mapped):

before after
largest computed module size ~2.3 GB ~0xae5f8 (≈700 KB)
modules spanning the cache ~all none
main executable extent 0x18000 0x18000 (unchanged)

Notes

This is the targeted bug fix. The proper long-term representation — per-segment ranges and rwx permissions from the real memory map — is tracked under #96; once that lands, this heuristic can be replaced. A comment in the code explains why the end is the owned range and not a naive max-over-sections, to prevent a regression re-adding it.

🤖 Generated with Claude Code

The LLDB adapter computed a module's size as `max(section end) - base`
over every section. On macOS this is broken: dyld groups the segments of
different modules by type into the shared cache (all __TEXT together, all
__DATA together, and a single ~600 MB __LINKEDIT shared by the whole
cache), so a module's own segments are scattered across gigabytes and many
modules point at the same __LINKEDIT. The max-end therefore spanned most of
the shared cache, making every module report a ~2.3 GB size and an end
address of -1 in the Modules panel.

Compute the extent from the header instead, keeping it to the range the
module actually owns via two signals: clip at the next module's load base,
and stop extending at the first large gap between the module's own
segments. On Linux and for the main executable on macOS (contiguous
segments) this yields the true full extent; for shared-cache dylibs it
yields the contiguous __TEXT range, matching `image list`/`vmmap`.

Verified against /usr/bin/ls with the shared cache mapped: the largest
computed module size drops from ~2.3 GB to ~700 KB and no module spans the
cache.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Debugger Modules shows wrong end addresses

1 participant